import re
import json
import demjson
import requests
from requests import ReadTimeout
from scrapy.http import HtmlResponse
from crawler.connection import redis_conn
from config.config import ABROAD_PROXY_LIST
from scrapy.downloadermiddlewares.retry import RetryMiddleware

proxies = {
    'http': 'http://%(username)s:%(password)s@%(host)s' % {
        'username': ABROAD_PROXY_LIST[0][0],
        'password': ABROAD_PROXY_LIST[0][1],
        'host': ABROAD_PROXY_LIST[0][2]
    },
    'https': 'http://%(username)s:%(password)s@%(host)s' % {
        'username': ABROAD_PROXY_LIST[0][0],
        'password': ABROAD_PROXY_LIST[0][1],
        'host': ABROAD_PROXY_LIST[0][2]
    }
}


class CookiesMiddleware(RetryMiddleware):
    cookies = None
    times = 0

    @staticmethod
    def get_cookies():
        session = requests.session()
        headers = {
            'Host': 'www.theoutnet.com',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
            'Accept-Language': 'zh-CN,zh;q=0.9',

        }
        response = session.get('https://www.theoutnet.com/en-hk/shop/clothing', headers=headers,
                               proxies=proxies, timeout=(30, 30), verify=False)
        cookies = response.cookies.get_dict()
        headers = {
            'Host': 'www.theoutnet.com',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
            'Accept': '*/*',
            'Origin': 'https://www.theoutnet.com',
            'Referer': 'https://www.theoutnet.com/en-hk/shop/clothing',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Content-Type': 'application/json',
        }
        regex = 'JSON.stringify\(\{\n.*,\n.*pow'

        bm_verify = re.search(regex, response.text).group().split(' "bm-verify":')[1].split(',')[0].strip().replace('"',
                                                                                                                    '')
        number_re = '<script\>\n.*var.i.*;\n.*;\n.*</script>'
        number_js = re.search(number_re, response.text).group().replace('<script>', '').replace('</script>', '').strip()
        number = eval(re.search('Number\(.*\);', number_js).group().replace('Number', '').replace(';', ''))
        i = re.search('var i =.*;', number_js).group().split('=')[1].replace(';', '').strip()
        number_result = eval(number) + eval(i)
        data = {
            "bm-verify": bm_verify,
            "pow": number_result
        }
        response = session.post('https://www.theoutnet.com/_sec/verify?provider=interstitial', headers=headers,
                                data=json.dumps(data), proxies=proxies, timeout=(30, 30), verify=False)
        cookies.update(response.cookies.get_dict())
        redis_conn.zadd(table='theoutnet_cookie_info', values=cookies)
        redis_conn.set_expire(key='theoutnet_cookie_info', seconds=600)
        return cookies

    def get_response(self, request, cookies):
        headers = {
            'Host': 'www.theoutnet.com',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
            'Referer': 'https://www.theoutnet.com/en-hk/shop/',
            'Accept-Language': 'zh-CN,zh;q=0.9',
        }
        response = requests.get(request.url, headers=headers, proxies=proxies, cookies=cookies, timeout=(30, 30))
        response = HtmlResponse(request.url, body=response.text, encoding='utf-8', request=request)
        return response

    def process_request(self, request, spider):
        if self.times > 50:
            self.cookies = None
            self.times = 0
        if not self.cookies:
            self.cookies = self.get_cookies()
        else:
            self.times += 1

        response = self.get_response(request, self.cookies)
        return response

    def process_response(self, request, response, spider):
        if "bm-verify" in response.text:
            self.cookies = None
            # redis_conn.zget(table='theoutnet_cookie_info')
            return self._retry(request, 'Error Cookies', spider)

        return response

    def process_exception(self, request, exception, spider):
        # 由于生成的cookie有可能不能用，会出现请求超时，此时只需要把cookie滞空进行重试即可
        if isinstance(exception, ReadTimeout):
            # self.max_retry_times = 5
            # 将retry_times的次数重置为0 ，避免直接跑错
            request.meta['retry_times'] = 0
            self.cookies = None
            redis_conn.zget(table='theoutnet_cookie_info')
            return self._retry(request, 'Exception Error Cookies', spider)
